import Store from '@/store'
import Utils from '@/uni_modules/yingbing-ui/js_sdk/util.js'
import Modules from '@/plugins/modules'
import Router from '@/plugins/router';
import Config from '@/assets/js/config.js';
import { com_prepose } from '@/assets/api/global.js';
import Api from '@/assets/api/index.js';
import Cache from '@/assets/constructor/cache.js';
import Source from '@/assets/constructor/source.js';
import Gather from '@/assets/constructor/gather.js';
import inSources from '@/assets/api/source.js';
import { simpleToTraditional, traditionalToSimple } from '@/assets/other/s2t.js';
import Trie from '@/assets/other/trie.js';
import Dict from '@/assets/other/dict.js'

const { getters, dispatch } = Store
const { suffix } = Utils
const { singleTypes, gatherTypes, characterTypes, ERR_OK, ERR_FALSE, app } = Config
export default {
	setSkinColor () {
		const skinColor = getters['app/skinColor']
		const skinMode = getters['app/skinMode']
		for ( let i = 0; i < 5; i++ ) {
			uni.setTabBarItem({
				index: i,
				iconfont: {
					color: skinColor.color_1,
					selectedColor: skinColor.color_actived_1,
				}
			})
		}
		uni.setTabBarStyle({
			color: skinColor.color_1,
			selectedColor: skinColor.color_actived_1,
			backgroundColor: skinColor.color_bg_1,
			midButton: {
				iconPath: 'static/mid/find-' + skinMode + '.png',
				iconWidth: "55px",
				height: "75px",
				text: "发现"
			},
			success: () => {},
			fail: () => {
			}
		})
	},
	//设置手机壁纸
	setWall (type = 'all', path) {
		let main = plus.android.runtimeMainActivity()
		let WallpaperManager = plus.android.importClass("android.app.WallpaperManager")
		let BitmapFactory = plus.android.importClass("android.graphics.BitmapFactory")
		let wallpaperManager = WallpaperManager.getInstance(main)
		plus.android.importClass(wallpaperManager)
		let filePath = plus.io.convertLocalFileSystemURL(path)
		let bitmap = BitmapFactory.decodeFile(filePath)
		try {
			if ( type == 'all' || type == 'wallpaper' ) wallpaperManager.setBitmap(bitmap) //设置壁纸
			if ( type == 'all' || type == 'lock' ) wallpaperManager.setBitmap(bitmap, null, true, WallpaperManager.FLAG_LOCK) //设置锁屏
			plus.android.invoke(bitmap, 'recycle')
			bitmap = null
			uni.showToast({
				title: "壁纸设置成功",
				icon: "none"
			})
		} catch (e) {
			uni.showToast({
				title: "壁纸设置失败",
				icon: "none"
			})
		}
	},
	//文件分享
	shareFile (path) {
		if ( path ) {
			this.selectReferer(path, true).then(src => {
				try{
					let main = plus.android.runtimeMainActivity();
					let Intent = plus.android.importClass("android.content.Intent");
					let MimeTypeMap = plus.android.importClass("android.webkit.MimeTypeMap");
					let file = plus.android.newObject('java.io.File', plus.io.convertLocalFileSystemURL(src))
					let accept = MimeTypeMap.getSingleton().getMimeTypeFromExtension(suffix(plus.android.invoke(file, 'getName')));
					let shareIntent = new Intent(Intent.ACTION_SEND);
					shareIntent.putExtra(Intent.EXTRA_STREAM, plus.io.convertLocalFileSystemURL(src));
					shareIntent.setType(accept ? accept : "*/*");
					main.startActivity(Intent.createChooser(shareIntent,"分享到"));
				}catch(e){
					uni.showToast({
						title: JSON.stringify(e),
						icon: 'none'
					})
				}
			})
		} else {
			uni.showToast({
				title: '文件路径无效',
				icon: 'none'
			})
		}
	},
	//网站分享
	shareWeb (params) {
		if ( !params ) {
			uni.showToast({
				title: '未传入分享对象',
				icon: 'none'
			})
			return
		}
		if ( !params.shareUrl ) {
			uni.showToast({
				title: '未传入分享链接',
				icon: 'none'
			})
			return
		}
		uni.showLoading({
			title: '正在加载资源'
		})
		let imageUrl = ''
		if ( Config.communityTypes.single[params.type] ) {
			params.list.forEach((item, key) => {
				if ( key == 0 ) {
					imageUrl = item.cover || item.avatar || item
				}
			})
		}
		if ( !imageUrl ) {
			imageUrl = this.getCover(params)
		}
		if ( imageUrl ) {
			this.selectReferer(imageUrl).then(src => {
				uni.getImageInfo({
					src: src,
					success: (rect) => {
						uni.showLoading({
							title: '正在生成海报'
						})
						let imageHeight = (700 / rect.width) * rect.height
						if ( imageHeight / 750 > 2 ) {
							imageHeight = 2 * 750
						}
						let height = imageHeight + 300
						let form = [{
							src: src,
							x: 25,
							y: 25,
							width: 700,
							height: imageHeight,
							type: 'image'
						},{
							text: params.title || params.name,
							x: 300,
							y: imageHeight + 80,
							color: '#333',
							size: 32,
							lines: 1,
							width: 445,
							style: 'fill',
							type: 'text'
						},{
							text: params.desc || '这是来自《' + this.filterSource(params.source).title + '》的' + this.getType(params.type),
							x: 280,
							y: imageHeight + 120,
							color: '#666',
							size: 24,
							width: 445,
							lineHeight: uni.upx2px(10),
							lines: 4,
							style: 'fill',
							type: 'text'
						},{
							x: 280,
							y: imageHeight + 240,
							color: this.getColor(params.type),
							width: this.getType(params.type).length * 38,
							height: 48,
							style: 'fill',
							type: 'rect'
						},{
							text: this.getType(params.type),
							x: 280 + (this.getType(params.type).length * 38 / 5),
							y: imageHeight + 272,
							color:'#fff',
							size: 24,
							lineHeight: uni.upx2px(10),
							style: 'fill',
							type: 'text'
						},{
							text: 'By   ' + Config.app.name,
							x: 580,
							y: imageHeight + 280,
							color: '#222',
							size: 18,
							style: 'fill',
							type: 'text'
						},{
							src: 'https://api.qrserver.com/v1/create-qr-code/?size=150x150&margin=10&data=' + params.shareUrl,
							x: 50,
							y: imageHeight + 50,
							width: 200,
							height: 200,
							type: 'image'
						},{
							text: '长按识别二维码',
							x: 80,
							y: imageHeight + 280,
							color: '#333',
							size: 20,
							style: 'fill',
							type: 'text'
						}]
						let options = {
							width: 750,
							height: height,
							background: '#ffffff',
							radius: 20
						}
						Router.push({
							path: '/modules/poster',
							animationType: 'fade-in',
							query: {
								form: encodeURIComponent(JSON.stringify(form)),
								options: encodeURIComponent(JSON.stringify(options))
							}
						})
					},
					fail: (err) => {
						uni.showToast({
							title: 'uni.getImageInfo:fail',
							icon: 'none'
						})
					}
				})
			})
		}
	},
	//预览图片
	async previewImage ({urls = [], current = 0, indicator = 'default', loop = false, success, fail, complete}) {
		let newUrls = []
		for( let url of urls ) {
			newUrls.push(await this.selectReferer(url))
		}
		uni.previewImage({
			urls: newUrls,
			current: current,
			longPressActions: {
				itemList: ['保存图片', '分享图片', '设为壁纸', '设为锁屏', '设为锁屏和壁纸'],
				success: (data) => {
					uni.showLoading({
						title: '图片下载中'
					})
					uni.downloadFile({
						url: urls[data.index],
						header: {
							Referer: urls[data.index]
						},
						success: (ret) => {
							uni.hideLoading()
							if (ret.statusCode === 200) {
								if ( data.tapIndex == 0 ) {
									uni.saveImageToPhotosAlbum({
										filePath: ret.tempFilePath,
										success: () => {
											uni.showToast({
												title: '已保存到相册',
												icon: 'none'
											})
										},
										fail: () => {
											uni.showToast({
												title: '保存到相册失败',
												icon: 'none'
											})
										}
									});
								} else if ( data.tapIndex == 1 ) {
									this.shareFile(ret.tempFilePath)
								} else {
									this.setWall(data.tapIndex == 2 ? 'wallpaper' : data.tapIndex == 3 ? 'lock' : 'all', ret.tempFilePath)
								}
							} else {
								uni.showToast({
									title: '图片下载失败',
									icon: 'none'
								})
							}
						},
						fail: (err) => {
							uni.showToast({
								title: '网络错误',
								icon: 'none'
							})
						}
					})
				},
				fail: function(err) {
					console.log(err.errMsg);
				}
			}
		})
	},
	//导入source
	leadSource ({sources, success, fail}) {
		let err = ''
		for ( let i = 0; i < sources.length; i++ ) {
			let source = sources[i]
			try{
				let sourceObj = this.sourceTextToJs(source)
				let index = getters['source/get'].findIndex(s => s.id == sourceObj.id)
				dispatch('source/add', sourceObj)
				success && success()
			}catch(e){
				err += e.toString() + (i < sources.length - 1 ? '\n' : '')
				continue
			}
		}
		if ( err ) {
			fail && fail(err)
		} else {
			success && success()
		}
	},
	//导出JSON
	deriveSource (source) {
		return new Promise(resolve => {
			plus.io.requestFileSystem(plus.io.PRIVATE_DOC, ( fs ) => {
				let file = plus.android.newObject("java.io.File", fs.root.fullPath + source.title + '.json');
				plus.android.invoke(file, 'createNewFile')
				let fileOutputStream = plus.android.newObject("java.io.FileOutputStream", file);
				let outputStreamWriter = plus.android.newObject("java.io.OutputStreamWriter", fileOutputStream, "utf-8");
				let bufferedWriter = plus.android.newObject("java.io.BufferedWriter", outputStreamWriter);
				plus.android.invoke(bufferedWriter, 'write', source.text ? JSON.stringify(source.text) : JSON.stringify(this.sourceJsToText(source)))
				plus.android.invoke(bufferedWriter, 'close')
				resolve({
					status: true,
					fileName: plus.android.invoke(file, 'getName'),
					root: fs.root.fullPath
				})
			}, ( e ) => {
				resolve({
					status: false,
					msg: e.message.toString() || '创建文件失败'
				})
			});
		})
	},
	//来源JS对象转文本
	sourceJsToText (source) {
		let text = '{'
		Object.keys(source).forEach(key => {
			if ( key == 'request' ) {
				let requestText = ''
				Object.keys(source[key]).forEach(k => {
					if ( source[key][k] && typeof source[key][k] == 'object' ) {
						let rtext = ''
						Object.keys(source[key][k]).forEach(rk => {
							if ( typeof source[key][k][rk] == 'string' ) {
								rtext += '"' + rk + '":"' + source[key][k][rk] + '",'
							} else if ( typeof source[key][k][rk] == 'function' ) {
								rtext += '"' + rk + '":' + source[key][k][rk].toString() + ','
							} else {
								rtext += '"' + rk + '":' + source[key][k][rk] + ','
							}
						})
						requestText += '"' + k + '":{' + rtext + '},'
					}
				})
				text += '"' + key + '":{' + requestText + '}'
			} else if ( key == 'custom' ) {
				if ( source[key] && typeof source[key] == 'object' ) {
					let customText = ''
					Object.keys(source[key]).forEach(k => {
						customText += '"' + k + '":' + source[key][k].toString() + ','
					})
					text += '"' + key + '":{' + customText + '},'
				}
			} else if ( key != 'open' ) {
				if ( typeof source[key] == 'string' ) {
					text += '"' + key + '":"' + source[key] + '",'
				} else {
					text += '"' + key + '":' + source[key] + ','
				}
			}
		})
		text += '}'
		return text
	},
	//格式化来源文本
	sourceTextToJs (data) {
		let result = eval('(' + data + ')')
		let custom = {}
		if ( result.custom ) {
			Object.keys(result.custom).forEach(key => {
				custom[key] = result.custom[key].toString()
			})
		}
		let request = {}
		Object.keys(result.request).forEach(key => {
			request[key] = Object.assign({}, result.request[key], {
				url: result.request[key].url.toString(),
				params: result.request[key].params.toString(),
				headers: result.request[key].headers.toString(),
				value: result.request[key].value.toString()
			})
		})
		return new Source({
			id: result.id,
			logo: result.logo,
			title: result.title,
			href: result.href,
			interval: result.interval,
			security: result.security,
			cover: result.cover,
			isAdult: result.isAdult,
			custom: custom.toString() == '{}' ? null : custom,
			request: request,
			text: data
		})
	},
	//打开详情
	openDetail (params, animationType = 'slide-in-right') {
		if ( !params ) {
			uni.showToast({
				title: '未传入资源对象',
				icon: 'none'
			})
			return
		}
		if ( params.isPay ) {
			uni.showToast({
				title: '付费资源请支持正版',
				icon: 'none'
			})
			return
		}
		if ( gatherTypes[params.type] ) {
			Router.push({
				path: '/pages/gather/detail',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( characterTypes.single[params.type] ) {
			Router.push({
				path: '/pages/user/detail',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( Config.bookTypes.single[params.type] ) {
			if ( params.source == 'local' ) {
				let index = getters['record/get'].findIndex(record => record.id == params.id)
				let record = index > -1 ? getters['record/get'][index].record : {
					start: 0,
					title: params.title
				}
				dispatch('reader/init', {
					book: params,
					record: record
				})
				Router.push({
					path: params.type == 'novel' ? '/pages/book/reader' : '/pages/comic/reader',
					animationType: animationType,
				})
			} else {
				Router.push({
					path: '/pages/book/detail',
					animationType: animationType,
					query: {
						params: encodeURIComponent(JSON.stringify(params))
					}
				})
			}
		} else if ( Config.videoTypes.single[params.type] ) {
			Router.push({
				path: '/pages/video/player',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( Config.liveTypes.single[params.type] ) {
			Router.push({
				path: '/pages/live/player',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( Config.communityTypes.single[params.type] ) {
			Router.push({
				path: '/pages/community/detail',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( Config.pictureTypes.single[params.type] ) {
			Router.push({
				path: '/pages/picture/detail',
				animationType: animationType,
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else if ( Config.audioTypes.single[params.type] ) {
			const currentId = getters['audio/getCurrentSong'] ? getters['audio/getCurrentSong'].id : ''
			if ( currentId != params.id ) {
				dispatch('audio/addSong', [params])
				setTimeout(() => {
					uni.$emit('switchSong', params)
				}, 100)
			}
			const pages = getCurrentPages()
			let index = pages.findIndex(page => page.route == 'pages/audio/player')
			index > -1 ? uni.navigateBack() : uni.$emit('goPlayer')
		} else {
			uni.showToast({
				title: '未知数据类型，请确认类型是否配置正确',
				icon: 'none'
			})
		}
	},
	getColor (type) {
		const skinColor = getters['app/skinColor']
		return Config.bookTypes.single[type] ? skinColor.color_red : Config.pictureTypes.single[type] ? skinColor.color_yellow : Config.videoTypes.single[type] ? skinColor.color_blue : Config.audioTypes.single[type] ? skinColor.color_green : Config.communityTypes.single[type] ? skinColor.color_orange : Config.liveTypes.single[type] ? skinColor.color_red_2 : skinColor.color_cyan
	},
	getType (type) {
		let types = Object.assign({}, singleTypes, gatherTypes, characterTypes.single)
		return (type && types[type]) || '未知类型'
	},
	getPartitionType (type) {
		let partitionType = ''
		Object.keys(Config.relation).forEach(key => {
			let arr = (Config.relation[key].single + ',' + Config.relation[key].gather).split(',').map(str => str.trim())
			if ( arr.indexOf(type) > -1 ) {
				partitionType = key
			}
		})
		return partitionType
	},
	getCover (params) {
		let cover = ''
		if ( params ) {
			cover = Config.characterTypes.single[params.type] ? params.avatar : params.cover
			if ( !cover && params.list.length > 0 ) {
				cover = params.list[0].type ? Config.characterTypes.single[params.list[0].type] ? params.list[0].avatar : params.list[0].cover : params.list[0]
			}
			if ( !cover ) {
				let source = this.filterSource(params.source)
				if ( source.cover ) {
					let arr = source.cover.split(',')
					return arr[Math.floor(Math.random()*arr.length)].trim()
				} else {
					return Config.audioTypes.single[params.type] ? '/static/cover/cover_audio_' + Math.floor(Math.random()*3 + 1) + '.jpg' : '/static/cover/cover_default_1.jpg'
				}
			}
		}
		return cover
	},
	//获取关键词
	getTag (params) {
		let type = this.getPartitionType(params.type)
		if ( type ) {
			let cc = params.title + '_' + params.creator + '_' + params.style + '_' + params.desc + '_' + params.content
			let dict = Dict[type] || []
			let str = simpleToTraditional(dict.toString())
			str = str + ',' + traditionalToSimple(str)
			str = str + ',' + str.toUpperCase()
			str = str + ',' + str.toLowerCase()
			dict = dict.concat(str.split(','))
			const trie = new Trie()
			trie.init([...new Set(dict)])
			return trie.splitWords(cc)
		} else {
			return []
		}
	},
	filterSource (source) {
		let sources = inSources.concat(getters['source/get'])
		let index = sources.findIndex(item => item.id == source)
		if ( index == -1 ) {
			return {
				id: source,
				title: app.name,
				logo: app.logo
			}
		} else {
			return sources[index]
		}
	},
	isCollection (id) {
		let defaultList = getters['collection/get'].filter(collection => collection.type != 'collectfolder')
		let folderList = getters['collection/get'].filter(collection => collection.type == 'collectfolder')
		if ( defaultList.findIndex(item => item.id == id) > -1 ) {
			return true
		}
		for ( let i = 0; i < folderList.length; i++ ) {
			if ( folderList[i].list.findIndex(item => item.id == id) > -1 ) {
				return true
			}
		}
		return false
	},
	toCollection (params) {
		if ( !params ) {
			return
		}
		
		Router.push({
			path: '/modules/collection',
			animationType: 'fade-in',
			query: {
				params: Utils.typeof(params) == 'Object' ? encodeURIComponent(JSON.stringify(params)) : '',
				list: Utils.typeof(params) == 'Array' ? encodeURIComponent(JSON.stringify(params)) : ''
			}
		})
	},
	isFollowee (id) {
		return getters['collection/get'].filter(collection => Config.characterTypes.single[collection.type]).findIndex(collection => collection.id == id) > -1
	},
	//关注
	toFollowee (params) {
		if ( !params ) {
			return
		}
		if ( this.isFollowee(params.id) ) {
			dispatch('collection/remove', params.id)
		} else {
			dispatch('collection/add', params)
		}
	},
	//跳转搜索页面
	toSearch (keyword, type) {
		Router.push({
			path: '/pages/search/result',
			animationType: 'slide-in-right',
			query: {
				keyword: encodeURIComponent(keyword),
				type: type || 'compress'
			}
		})
	},
	//展示标签列表
	showTaglist (keyword, type) {
		Router.push({
			path: '/modules/taglist',
			animationType: 'fade-in',
			query: {
				keyword: encodeURIComponent(keyword),
				type: type || 'compress'
			}
		})
	},
	//展示评论
	showComment (params) {
		if ( params ) {
			Router.push({
				path: '/modules/comment',
				animationType: 'fade-in',
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else {
			uni.showToast({
				title: '请传入评论对象',
				icon: 'none'
			})
		}
	},
	//展示相关推荐
	showRecome (params) {
		if ( params ) {
			Router.push({
				path: '/modules/recome',
				animationType: 'fade-in',
				query: {
					params: encodeURIComponent(JSON.stringify(params))
				}
			})
		} else {
			uni.showToast({
				title: '请传入推荐对象',
				icon: 'none'
			})
		}
	},
	//设置防盗链
	async selectReferer (src, flag = false) {
		let sources = inSources.concat(getters['source/get']).filter(source => source.security)
		let referers = getters['referer/get']
		sources.forEach(source => {
			referers = referers.concat(source.security.split(',').map(s => s.trim()))
		})
		if ( referers.findIndex(referer => src.indexOf(referer) > -1) > -1 || flag ) {
			const caches = getters['cache/get'];
			const index = caches.findIndex(cache => cache.parentId == src + '_referer')
			if ( index > -1 ) {
				const url = plus.io.convertLocalFileSystemURL(caches[index].src);
				const file = plus.android.newObject('java.io.File', url);
				if ( plus.android.invoke(file, 'exists') ) {
					return caches[index].src
				} else {
					dispatch('cache/remove', id)
				}
			} else if ( src.slice(0, 4) == 'http' ) {
				const download = function () {
					return new Promise(resolve => {
						uni.downloadFile({
							header: {
								Referer: src
							},
							url: src,
							success: (res) => {
								if (res.statusCode === 200) {
									dispatch('cache/add', new Cache({
										parentId: src + '_referer',
										src: res.tempFilePath,
										type: 'image'
									}))
									resolve(res.tempFilePath)
								} else {
									resolve(src)
								}
							},
							fail: (err) => {
								resolve(src)
							}
						})
					})
				}
				return await download().then(path => {
					return path
				})
			}
		}
		return src
	},
	async requestApis ({
		name, type, data={}, pagings = {}, size = 1, isLastPages={}, requestTime=0, source = ''
	}) {
		let types = []
		if ( type == 'compress' ) {
			types = Object.keys( Object.assign({}, singleTypes, gatherTypes, characterTypes) )
		} else if ( type == 'single' ) {
			types = Object.keys( singleTypes )
		} else if ( type == 'gather' ) {
			types = Object.keys( gatherTypes )
		} else if ( type == 'character' ) {
			types = Object.keys( characterTypes.single )
		} else {
			types = type.split(',').map(t => t.trim())
		}
		let names = types.map(t => name + '_' + t)
		source = source ? source.split(',').map(s => s.trim()) : []
		let sources = inSources.concat(getters['source/get']).filter(s => getters['source/getBlacklist'].indexOf(s.id) == -1 && (!s.isAdult || getters['app/getAdult']) && (source.length == 0 || source.indexOf(s.id) > -1 ) )
		let arr = []
		let newArr = []
		sources.forEach(sou => {
			Object.keys(sou.request).forEach(key => {
				if ( sou.request[key] && sou.request[key].value && names.indexOf(key) > -1 ) {
					arr.push({
						data: Object.assign({}, data, {
							source: sou.id,
							paging: pagings[key + '_' + sou.id] || {}
						}),
						key: key + '_' + sou.id,
						name: key
					})
				}
			})
		})
		newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
		let isEnd = (requestTime + 1) * size > arr.length - 1
		while ( newArr.length == 0 && !arr.every(item => isLastPages[item.key]) ) {
			requestTime++
			newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
			isEnd = (requestTime + 1) * size > arr.length - 1
			if ( isEnd ) {
				requestTime = -1
				data.currentPage >= 0 ? data.currentPage++ : null
			}
		}
		newArr = newArr.map(item => {
			return Object.assign({}, item, {
				data: Object.assign({}, item.data, data)
			})
		})
		if ( newArr.length > 0 ) {
			return await com_prepose(newArr).then(ress => {
				let list = []
				ress.forEach((res, i) => {
					if ( res.code == ERR_OK && res.data && res.data.list ) {
						list = list.concat(res.data?.list)
						pagings[newArr[i].key] = res.data.paging || {}
						isLastPages[newArr[i].key] = res.data.isLastPage || res.data.list.length == 0
					} else {
						pagings[newArr[i].key] = {}
						isLastPages[newArr[i].key] = true
					}
				})
				return {
					list: list,
					isLastPage: arr.every(item => isLastPages[item.key]),
					isLastPages: isLastPages,
					pagings: pagings,
					requestTime: isEnd ? 0 : requestTime + 1,
					currentPage: data.currentPage >= 0 ? isEnd ? data.currentPage + 1 : data.currentPage : null
				}
			})
		} else {
			return {
				list: [],
				isLastPage: true,
				isLastPages: {},
				pagings: {},
				requestTime: 0,
				currentPage: 1
			}
		}
	},
	//根据资源获取相关作品
	async getRecome ({
		params={}, type, size=1, currentPage=1, pagings={}, isLastPages={}, requestTime=0, requestIndex=0, by = 'record'
	}) {
		let singles = params.id ? [params] : []
		let types = []
		if ( type == 'compress' ) {
			types = Object.keys( Object.assign({}, singleTypes, gatherTypes, characterTypes) )
		} else if ( type == 'single' ) {
			types = Object.keys( singleTypes )
		} else if ( type == 'gather' ) {
			types = Object.keys( gatherTypes )
		} else if ( type == 'character' ) {
			types = Object.keys( characterTypes.single )
		} else {
			types = type.split(',').map(t => t.trim())
		}
		if ( by == 'collection' ) {
			let folders = getters['collection/get'].filter(collect => collect.type == 'collectfolder' && (!collect.isAdult || getters['app/getAdult']))
			folders.forEach(folder => {
				singles = singles.concat(folder.list.filter(sin => types.indexOf(sin.type) > -1 && (!sin.isAdult || getters['app/getAdult'])))
			})
		}
		if ( by == 'record' ) {
			singles = singles.concat(getters['record/get'].filter(record => types.indexOf(record.type) > -1 && (!record.isAdult || getters['app/getAdult']) ) )
		}
		let recome = JSON.parse(JSON.stringify(singles[requestIndex]))
		let sources = inSources.concat(getters['source/get']).filter(s => getters['source/getBlacklist'].indexOf(s.id) == -1 && (!s.isAdult || getters['app/getAdult']) )
		let arr = []
		let newArr = []
		sources.forEach(sou => {
			Object.keys(sou.request).forEach(key => {
				if ( sou.request[key] && sou.request[key].value && recome.source == sou.id && key == 'getRecome_' + recome.type ) {
					arr.push({
						data: Object.assign({}, recome, {
							source: sou.id,
							paging: pagings[key + '_' + sou.id + '_' + recome.id] || {},
							currentPage: currentPage
						}),
						key: key + '_' + sou.id + '_' + recome.id,
						name: key
					})
				}
			})
		})
		let tagList = recome.tag
		if ( recome.title ) {
			tagList.push(recome.title)
		}
		if ( recome.name ) {
			tagList.push(recome.name)
		}
		if ( recome.creator ) {
			tagList.push(recome.creator)
		}
		tagList = [...new Set(tagList)]
		let searchname = 'search_' + recome.type
		tagList.forEach(tag => {
			sources.forEach(sou => {
				Object.keys(sou.request).forEach(key => {
					let index = arr.findIndex(item => item.key == key + '_' + sou.id + '_' + tag)
					if ( key == searchname && sou.request[key] && sou.request[key].value && index == -1 ) {
						arr.push({
							data: {
								keyword: tag,
								source: sou.id,
								paging: pagings[key + '_' + sou.id + '_' + tag] || {},
								currentPage: currentPage
							},
							key: key + '_' + sou.id + '_' + tag,
							name: key
						})
					}
				})
			})
		})
		newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
		let isEnd = (requestTime + 1) * size > arr.length - 1
		while ( newArr.length == 0 && !arr.every(item => isLastPages[item.key]) ) {
			requestTime++
			newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
			isEnd = (requestTime + 1) * size > arr.length - 1
			if ( isEnd ) {
				requestTime = -1
				currentPage >= 0 ? currentPage++ : null
			}
		}
		newArr = newArr.map(item => {
			return Object.assign({}, item, {
				data: Object.assign({}, item.data, {
					currentPage: currentPage
				})
			})
		})
		if ( newArr.length > 0 ) {
			return await com_prepose(newArr).then(ress => {
				let list = []
				ress.forEach((res, i) => {
					if ( res.code == ERR_OK && res.data && res.data.list ) {
						list = list.concat(res.data?.list)
						pagings[newArr[i].key] = res.data.paging || {}
						isLastPages[newArr[i].key] = res.data.isLastPage || res.data.list.length == 0
					} else {
						pagings[newArr[i].key] = {}
						isLastPages[newArr[i].key] = true
					}
				})
				return {
					list: list,
					isLastPage: arr.every(item => isLastPages[item.key]) && requestIndex == singles.length - 1,
					pagings: pagings,
					isLastPages: isLastPages,
					requestTime: isEnd ? 0 : requestTime + 1,
					currentPage: isEnd ? currentPage + 1 : currentPage,
					requestIndex: isEnd ? requestIndex + 1 > singles.length - 1 ? 0 : requestIndex + 1 : requestIndex
				}
			})
		} else {
			return {
				list: [],
				isLastPage: true,
				pagings: {},
				isLastPages: {},
				requestTime: 0,
				currentPage: 1,
				requestIndex: 0
			}
		}
	},
	//根据关注获取相关作品
	async getFolloweeList ({
		type, size=1, currentPage=1, pagings={}, isLastPages={}, requestTime=0
	}) {
		let characters = JSON.parse(JSON.stringify(getters['collection/get'].filter(co => Config.characterTypes.single[co.type])))
		let types = []
		if ( type == 'compress' ) {
			types = Object.keys( Object.assign({}, singleTypes, gatherTypes, characterTypes) )
		} else if ( type == 'single' ) {
			types = Object.keys( singleTypes )
		} else if ( type == 'gather' ) {
			types = Object.keys( gatherTypes )
		} else if ( type == 'character' ) {
			types = Object.keys( characterTypes.single )
		} else {
			types = type.split(',').map(t => t.trim())
		}
		let sources = inSources.concat(getters['source/get']).filter(s => getters['source/getBlacklist'].indexOf(s.id) == -1 && (!s.isAdult || getters['app/getAdult']) )
		let arr = []
		let newArr = []
		characters.forEach(character => {
			sources.forEach(sou => {
				Object.keys(sou.request).forEach(key => {
					if ( sou.request[key] && sou.request[key].value && character.source == sou.id &&  types.map(t => 'getCharacterWorksList_' + character.type + '_' + t ).indexOf(key) > -1 ) {
						arr.push({
							data: Object.assign({}, character, {
								source: sou.id,
								paging: pagings[key + '_' + sou.id + '_' + character.id] || {},
								currentPage: currentPage
							}),
							key: key + '_' + sou.id + '_' + character.id,
							name: key
						})
					}
				})
			})
		})
		newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
		let isEnd = (requestTime + 1) * size > arr.length - 1
		while ( newArr.length == 0 && !arr.every(item => isLastPages[item.key]) ) {
			requestTime++
			newArr = arr.slice(requestTime * size, ((requestTime + 1) * size)).filter(item => !isLastPages[item.key])
			isEnd = (requestTime + 1) * size > arr.length - 1
			if ( isEnd ) {
				requestTime = -1
				currentPage >= 0 ? currentPage++ : null
			}
		}
		newArr = newArr.map(item => {
			return Object.assign({}, item, {
				data: Object.assign({}, item.data, {
					currentPage: currentPage
				})
			})
		})
		if ( newArr.length > 0 ) {
			return await com_prepose(newArr).then(ress => {
				let list = []
				ress.forEach((res, i) => {
					if ( res.code == ERR_OK && res.data && res.data.list ) {
						list = list.concat(res.data?.list)
						pagings[newArr[i].key] = res.data.paging || {}
						isLastPages[newArr[i].key] = res.data.isLastPage || res.data.list.length == 0
					} else {
						pagings[newArr[i].key] = {}
						isLastPages[newArr[i].key] = true
					}
				})
				return {
					list: list,
					isLastPage: arr.every(item => isLastPages[item.key]),
					pagings: pagings,
					isLastPages: isLastPages,
					requestTime: isEnd ? 0 : requestTime + 1,
					currentPage: isEnd ? currentPage + 1 : currentPage
				}
			})
		} else {
			return {
				list: [],
				isLastPage: true,
				pagings: {},
				isLastPages: {},
				requestTime: 0,
				currentPage: 1
			}
		}
	}
}